<?php


/** ensure this file is being included by a parent file */
defined('_JEXEC') or die('Restricted access');

class HelpDeskHelperCategory 
{
	/**
	 * Returns an object
	 * @param mixed Boolean
	 * @return array
	 */
	function &getInstance( $id='0' ) 
	{
		$id = intval($id);
				
		HelpDeskTable::addIncludePath( JPATH_ADMINISTRATOR.DS.'components'.DS.'com_helpdesk'.DS.'tables'.DS );
		unset($row);
		$row = HelpDeskTable::getInstance( 'category', 'Table' );
		$row->load( $id );
		
		return $row;
	}

	/**
	 * Returns a list of types
	 * @param mixed Boolean
	 * @param mixed Boolean
	 * @return array
	 */
	function getAll( $published='1' ) 
	{
		$database = HelpDeskConfig::getDBO();

		$where = array();
		$lists = array();

		$published_query = "";
		if (intval($published) > 0) { $published_query = " AND db.published = '1' "; }
			
		$query = "
			SELECT
				db.*
			FROM
				#__helpdesk_categories AS db
			WHERE 1
				{$published_query}
			ORDER BY
				db.ordering ASC
		";

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		return $data;
	}

	/**
	 * Returns a list of types
	 * @param mixed Boolean
	 * @param mixed Boolean
	 * @return array
	 */
	function getChildren( $parent=0, $published=0 ) 
	{
		$database = HelpDeskConfig::getDBO();

		$published_query = "";

		$parent_query = " AND c.parentid = '".intval($parent)."' ";
		if (intval($published) > 0) { $published_query = " AND c.published = '1' "; }
	
		$query = "
			SELECT 
				c.* 
			FROM 
				#__helpdesk_categories AS c
			WHERE 1
				{$parent_query}
				{$published_query}
			ORDER BY 
				c.ordering ASC
		";

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		return $data;
	}
		
	/**
	 * Get the tree
	 * @return array
	 */
	function getTreeRecursive( $parent='0', $published='0', $indent='.&nbsp;&nbsp;', $level=0, $list=array() ) 
	{
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();

		// HelpDeskTable::addIncludePath( JPATH_ADMINISTRATOR.DS.'components'.DS.'com_helpdesk'.DS.'tables'.DS );
		
		unset($root);
		$root = HelpDeskTable::getInstance( 'category', 'Table' );
		$root->load( (int) $parent );
		$root->nodetitle = str_repeat( $indent, $level ).HelpDeskText::_( $root->title );
		$list[$root->id] = $root;
				
		if (!$descendants = HelpDeskHelperCategory::getChildren( intval($root->id), $published ) ) 
		{
			return $list;
		}

		$level++;
		// display each row
	   	for ($i=0; $i<count($descendants); $i++) 
	   	{
	   		$row = $descendants[$i];
			if (isset($list[$row->id])) {
				continue;
			}
			// display indented node title
			$row->nodetitle = str_repeat( $indent, $level ).HelpDeskText::_( $row->title );
			$list[$row->id] = $row;
			$list = HelpDeskHelperCategory::getTreeRecursive( $row->id, $published, $indent, $level, $list );
	   	}
		
		return $list;
	}
	
	/**
	 * Get the tree
	 * @return array
	 */
	function getTree( $node='0', $indent='.&nbsp;&nbsp;', $type=1 ) 
	{
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		
		HelpDeskTable::addIncludePath( JPATH_COMPONENT_ADMINISTRATOR.DS.'tables'.DS );
		
		unset($root);
		$root = HelpDeskTable::getInstance( 'category', 'Table' );
		$root->load( (int) $node );
	
		// start with an empty $right stack
		$right = array();
		
		if ( !$descendants = HelpDeskHelperCategory::getDescendants( $root ) ) {
			return $success;
		}

		// display each row
	   	for ($i=0; $i<count($descendants); $i++) {
	   		$row = $descendants[$i];
			
			// only check stack if there is one
			if ( count($right) > 0 ) {
				// check if we should remove a node from the stack
				while ($right[count($right)-1] < $row->rgt) {
					array_pop($right);
				}
			}
			
			// display indented node title
			$return[$i] = $row;
			$return[$i]->nodetitle = str_repeat( $indent, count($right) ).HelpDeskText::_( $row->title );
			
			// add this node to the stack
			$right[] = $row->rgt;
	   	}
		
		return $return;
	}
	
	/**
	 * Find the path to a node
	 * @return array
	 */
	function getPath( $node ) {
		$success = false;
		$database = HelpDeskConfig::getDBO();
		
		if (!is_object($node)) {
			// attempt to get it
			$node = HelpDeskHelperCategory::getInstance( intval($node) );
			if (!$node->id) { return $success; }
		}

		$query = "SELECT t.* FROM #__helpdesk_categories AS t "
		. " WHERE `lft` < '".$node->lft."' AND `rgt` > '".$node->rgt."' "
		. " ORDER BY `lft` ASC "
		;

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		$success = $data;

		return $success;
	}

	/**
	 * Get node descendants
	 * @param object
	 * @return array
	 */
	function getDescendants( $node, $published='0' ) {
		$success = false;
		$database = HelpDeskConfig::getDBO();
		$published_query = "";
		
		if (!is_object($node)) { return $success; }
		
		if (intval($published) > 0) { $published_query = " AND t.published = '1' "; }
		
		if ($hasDescendants = HelpDeskHelperCategory::hasDescendants( $node )) {
			$query = "SELECT t.* FROM #__helpdesk_categories AS t "
			. " WHERE `lft` BETWEEN '".$node->lft."' AND '".$node->rgt."' "
			. $published_query
			. " ORDER BY `lft` ASC "
			;
	
			$database->setQuery( $query );
			$data = $database->loadObjectList();
			
			$success = $data;
		}
		
		return $success;
	}
	
	/**
	 * Determines whether node has descendants
	 * @param object
	 * @return boolean
	 */
	function hasDescendants( $node ) {
		$success = '0';
		$descendants = ($node->rgt - $node->lft - 1) / 2;
		if (intval($descendants) > 0) { return $descendants; }
		else { return $success; }
	}

	/**
	 * Store a node
	 * @param object
	 * @return boolean
	 */
	function storeNode( &$node ) {
		$success = false;
		$database = HelpDeskConfig::getDBO();
		
		if (!is_object($node)) { return $success; }
		
		if (intval($node->id) > 0) {
			$store = HelpDeskHelperCategory::updateNode( $node );
		} else {
			$store = HelpDeskHelperCategory::insertNode( $node );
		}
		
		HelpDeskHelperCategory::rebuildTree();
		HelpDeskHelperCategory::rebuildTreeUnpublished();
				
		return $store;
	}

	/**
	 * Inserts a node
	 * @param object
	 * @return boolean
	 */
	function insertNode( &$node ) {
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		if (!is_object($node)) { return $success; }
		
		HelpDeskTable::addIncludePath( JPATH_COMPONENT_ADMINISTRATOR.DS.'tables'.DS );
		
		unset($parent);
		$parent = HelpDeskTable::getInstance( 'category', 'Table' );
		$parent->load( (int) $node->parentid );
		
		// get rgt value of parentid
		$parent_rgt = $parent->rgt - 1;

			$query = "UPDATE #__helpdesk_categories "
			. " SET `rgt` = rgt+2 "
			. " WHERE `rgt` > '".$parent_rgt."' "
			;
	
			$database->setQuery( $query );
			$database->query();
			
			$query = "UPDATE #__helpdesk_categories "
			. " SET `lft` = lft+2 "
			. " WHERE `lft` > '".$parent_rgt."' "
			;
	
			$database->setQuery( $query );
			$database->query();
		
		// insert the new node
		$node->lft = $parent->rgt;
		$node->rgt = $parent->rgt + 1;

   		// Store the entry
    	if (!$node->store()) { return $success; }
		
		$success = true;
		return $success;
	}
	
	/**
	 * Updates a node
	 * @param object
	 * @return boolean
	 */
	function updateNode( &$node ) {
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		if (!is_object($node)) { return $success; }
		
		if (!intval($node->id) > 0) {
			return success;
		}
		
		$node->store();
		HelpDeskHelperCategory::rebuildTree();

			$config = &HelpDeskConfig::getInstance();
			$cats_usedropdown = $config->get( 'cats_usedropdown', '1' );
			if ($cats_usedropdown) {
				HelpDeskHelperCategory::rebuildTreeUnpublished();
			}
		
		$success = true;
		return $success;
	}

	/**
	 * Delete a node
	 * @param object
	 * @return boolean
	 */
	function deleteNode( &$node ) {
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		if (!is_object($node)) { return $success; }
		
		if (!intval($node->id) > 0) {
			return success;
		}
		
		$node->delete();
		$descendants = HelpDeskHelperCategory::getDescendants( $node );
		for ($i=0; $i<count($descendants); $i++) {
			$row = $descendants[$i];
			$node->delete( $row->id );
		}
		
		HelpDeskHelperCategory::rebuildTree();
		HelpDeskHelperCategory::rebuildTreeUnpublished();
		
		$success = true;
		return $success;
	}

	/**
	 * Un/Publish a node
	 * @param object
	 * @return boolean
	 */
	function publishNode( &$node, $published=null ) {
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		if (!is_object($node)) { return $success; }
		
		if (!intval($node->id) > 0) {
			return success;
		}

		// change published
		if (isset($published)) {
			$node->published = $published;
		} else {
			if ($node->published == 1) { $node->published = 0; } else { $node->published = 1; }
			$published = $node->published;
		}
				
		$node->store();

		HelpDeskTable::addIncludePath( JPATH_COMPONENT_ADMINISTRATOR.DS.'tables'.DS );
						
		$descendants = HelpDeskHelperCategory::getChildren( $node->id, '-1' );
		
		for ($i=0; $i<count($descendants); $i++) {
			$row = $descendants[$i];
			unset($currentNode);
			$currentNode = HelpDeskTable::getInstance( 'category', 'Table' );
			$currentNode->load( (int) $row->id );

			HelpDeskHelperCategory::publishNode( $currentNode, $published );
		}

		HelpDeskHelperCategory::rebuildTree();
		HelpDeskHelperCategory::rebuildTreeUnpublished();
	
		$success = true;
		return $success;
	}

	/**
	 * Rebuilds the Tree
	 * @param object
	 * @return boolean
	 */
	function rebuildTree( $parent=0, $left=1 ) {
		$database = HelpDeskConfig::getDBO();
		// the right value of this node is the left value + 1
		$right = $left+1;
		
		// get all children of this node
		$children = HelpDeskHelperCategory::getChildren( $parent );
		for ($i=0; $i<count($children); $i++) {
			$row = $children[$i];
			// recursive execution of this function for each
			// child of this node
			// $right is the current right value, which is
			// incremented by the rebuild_tree function
			$right = HelpDeskHelperCategory::rebuildTree( $row->id, $right );

		}
		
			// we've got the left value, and now that we've processed
			// the children of this node we also know the right value
			$query = "UPDATE #__helpdesk_categories "
			. " SET `rgt` = '".$right."', "
			. " `lft` = '".$left."' "
			. " WHERE `id` = '".$parent."' "
			;
			$database->setQuery( $query );
			$database->query();
					
		// return the right value of this node + 1
		return $right+1;
	}

	/**
	 * Rebuilds the Tree
	 * @param object
	 * @return boolean
	 */
	function rebuildTreeUnpublished( $parent=0, $left=1 ) {
		$database = HelpDeskConfig::getDBO();
		// the right value of this node is the left value + 1
		$right = $left+1;
		
		// get all children of this node
		$children = HelpDeskHelperCategory::getChildren( $parent, '-1' );
		for ($i=0; $i<count($children); $i++) {
			$row = $children[$i];
			// recursive execution of this function for each
			// child of this node
			// $right is the current right value, which is
			// incremented by the rebuild_tree function
			$right = HelpDeskHelperCategory::rebuildTreeUnpublished( $row->id, $right );

		}
		
			// we've got the left value, and now that we've processed
			// the children of this node we also know the right value
			$query = "UPDATE #__helpdesk_categories "
			. " SET `rgt_all` = '".$right."', "
			. " `lft_all` = '".$left."' "
			. " WHERE `id` = '".$parent."' "
			;
			$database->setQuery( $query );
			$database->query();
					
		// return the right value of this node + 1
		return $right+1;
	}

	/**
	 * Get the tree
	 * @return array
	 */
	function getTreeUnpublished( $node, $indent='.&nbsp;&nbsp;', $type=1 ) {
		$success = false;
		$return = array();
		$database = HelpDeskConfig::getDBO();
		
		HelpDeskTable::addIncludePath( JPATH_COMPONENT_ADMINISTRATOR.DS.'tables'.DS );
		
		unset($root);
		$root = HelpDeskTable::getInstance( 'category', 'Table' );
		$root->load( (int) $node );
	
		// start with an empty $right stack
		$right = array();
		
		if ( !$descendants = HelpDeskHelperCategory::getDescendantsUnpublished( $root, '-1' ) ) {
			return $success;
		}

		// display each row
	   	for ($i=0; $i<count($descendants); $i++) {
	   		$row = $descendants[$i];
			
			// only check stack if there is one
			if ( count($right) > 0 ) {
				// check if we should remove a node from the stack
				while ($right[count($right)-1] < $row->rgt_all) {
					array_pop($right);
				}
			}
			
			// display indented node title
			$return[$i] = $row;
			$return[$i]->nodetitle = str_repeat( $indent, count($right) ).HelpDeskText::_( $row->title );
			
			// add this node to the stack
			$right[] = $row->rgt_all;
	   	}
		
		return $return;
	}
	
	/**
	 * Find the path to a node
	 * @return array
	 */
	function getPathUnpublished( $node ) {
		$success = false;
		$database = HelpDeskConfig::getDBO();
		
		if (!is_object($node)) { return $success; }

		$query = "SELECT t.* FROM #__helpdesk_categories AS t "
		. " WHERE `lft_all` < '".$node->lft_all."' AND `rgt_all` > '".$node->rgt_all."' "
		. " ORDER BY `lft_all` ASC "
		;

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		$success = $data;

		return $success;
	}

	/**
	 * Get node descendants
	 * @param object
	 * @return array
	 */
	function getDescendantsUnpublished( $node, $published='1' ) {
		$success = false;
		$database = HelpDeskConfig::getDBO();
		$published_query = "";
		
		if (!is_object($node)) { return $success; }
		
		if (intval($published) > 0) { $published_query = " AND t.published = '1' "; }
		
		if ($hasDescendants = HelpDeskHelperCategory::hasDescendantsUnpublished( $node )) {
			$query = "SELECT t.* FROM #__helpdesk_categories AS t "
			. " WHERE `lft_all` BETWEEN '".$node->lft_all."' AND '".$node->rgt_all."' "
			. $published_query
			. " ORDER BY `lft_all` ASC "
			;
	
			$database->setQuery( $query );
			$data = $database->loadObjectList();
			
			$success = $data;
		}
		
		return $success;
	}
	
	/**
	 * Determines whether node has descendants
	 * @param object
	 * @return boolean
	 */
	function hasDescendantsUnpublished( $node ) {
		$success = '0';
		$descendants = ($node->rgt_all - $node->lft_all - 1) / 2;
		if (intval($descendants) > 0) { return $descendants; }
		else { return $success; }
	}

	/**
	 * Creates a List
	 * @return array Array of objects containing the data from the database
	 */
	function getSelectListTypes( $exception='', $published='-1' ) 
	{
		$done = array();
		static $_selectListTypes;
		
		if (empty($_selectListTypes)) {
			$types[] = HelpDeskHTML::selectOption( '', '- '.HelpDeskText::_( 'Select from List' ).' -' );
			// $data = &HelpDeskHelperCategory::getTree( 0 );
			$data = HelpDeskHelperCategory::getTreeRecursive(0, $published);
			// plugin event here to enables filtering of list of categories by any plugin
			$dispatcher		=& HelpDeskHelperPlugin::getInstance();
			$beforeView		= $dispatcher->trigger( 'onGetSelectListTypes_Categories_HelpDesk', array( $data ) );
			if ($data) {
			  foreach ($data as $d) {
			  	if ($d->id > 0) {
			  		if (intval($exception) != $d->id) {
				  		$types[] = HelpDeskHTML::selectOption( $d->id, HelpDeskText::_( $d->nodetitle ) );
			  		}
			  	}
			  }
			}
		
			$_selectListTypes = $types;
		
		}
		
		return $_selectListTypes;
	}

	/**
	 *
	 * @return
	 * @param $field Object
	 * @param $default Object[optional]
	 * @param $options Object[optional]
	 */
	function getSelectList( $field, $default='', $options='' )
	{
		return HelpDeskHTML::genericList( HelpDeskHelperCategory::getSelectListTypes(), $field, $options, 'value','text', $default);
	}
	
	/**
	 * 
	 * @return unknown_type
	 */
	function getManagers( $id )
	{
		$database = HelpDeskConfig::getDBO();		
		
		$where = array();
		$lists = array();
		$nodupes = array();
		
		$item = HelpDeskHelperCategory::getInstance( $id );
		$where[] = $item->id;
		if ($item->parentid) {
			$parent = HelpDeskHelperCategory::getInstance( $item->parentid );
			$where[] = $parent->id;	
		}
		$cat_query = " AND t.categoryid IN ('".implode( "', '", $where )."') ";
		
		$query = "
			SELECT 
				u.*, t.categoryid 
			FROM 
				#__helpdesk_u2c AS t
				LEFT JOIN #__users AS u ON t.userid = u.id
			WHERE 1
				{$cat_query}
		";

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		for ($i=0; $i<count($data); $i++) 
		{
			$d = $data[$i];
			if ($d->id > 0 && !isset($nodupes[$d->id])) 
			{
				$lists[] = $d;
				$nodupes[$d->id] = $d->id;	
			}
		}

		return $lists;
	}
	
	/**
	 * 
	 * @param $id
	 * @return unknown_type
	 */
	function getFields( $id ) 
	{
		$database = HelpDeskConfig::getDBO();

		$where = array();
		$lists = array();
		$nodupes = array();
		HelpDeskTable::addIncludePath( JPATH_COMPONENT_ADMINISTRATOR.DS.'tables'.DS );
		
		$cat_query = " AND t.categoryid = '".$id."' ";
		$field_query = " AND f.published = '1' ";
		$order_query = " ORDER BY f.ordering ASC "; 
		
		// all records		
		$query = "
			SELECT 
				t.* 
			FROM 
				#__helpdesk_f2c AS t
				INNER JOIN #__helpdesk_fields AS f ON t.fieldid = f.id
			WHERE 1
				{$cat_query}
				{$field_query}
				{$order_query}
		";

		$database->setQuery( $query );
		$data = $database->loadObjectList();
		
		for ($i=0; $i<count($data); $i++) {
			if ($data[$i]->fieldid > 0) {
				unset($table);
				$table = HelpDeskTable::getInstance( 'field', 'Table' );
				$table->load( $data[$i]->fieldid );
				$lists[] = $table;
				$nodupes[$data[$i]->fieldid] = $data[$i]->fieldid;
			}
		}
		
		// does the category have a parent?
		$query = "SELECT `parentid` FROM #__helpdesk_categories "
		. " WHERE `id` = '".$id."' "
		;
		$database->setQuery( $query );
		if ( $parentid = $database->loadResult() ) {
			if ( intval($parentid) > 0) {
				// does the parent have fields assigned to it?
				$cat_query = " AND t.categoryid = '".$parentid."' ";	
				$query = "SELECT t.* FROM #__helpdesk_f2c AS t "
				. " INNER JOIN #__helpdesk_fields AS f ON t.fieldid = f.id "
				. " WHERE 1 "
				. $cat_query
				;
				$database->setQuery( $query );
				$data = $database->loadObjectList();
				for ($i=0; $i<count($data); $i++) {
					if (empty($nodupes[$data[$i]->fieldid])) {
						if ($data[$i]->fieldid > 0) {
							unset($table);
							$table = HelpDeskTable::getInstance( 'field', 'Table' );
							$table->load( $data[$i]->fieldid );
							$lists[] = $table;
							$nodupes[$data[$i]->fieldid] = $data[$i]->fieldid;
						}
					}
				}
			}			
		}	
		
		return $lists;
	}
	
	/**
	 * 
	 * @param $userid
	 * @param $catid
	 * @param $returnObject
	 * @return unknown_type
	 */
	function isField( $catid, $fieldid, $returnObject='0' ) 
	{
        $success = false;
        $database = HelpDeskConfig::getDBO();
        
        $query = "
            SELECT
                *
            FROM
                #__helpdesk_f2c
            WHERE
                `fieldid` = '{$fieldid}'
            AND
                `categoryid` = '{$catid}'
            LIMIT 1
        ";
        $database->setQuery( $query );
        $data = $database->loadObject();
        if ( $data ) {
            $success = true;
            
            if ($returnObject == '1') {
                $success = $data;
            }
        }
        
        return $success;
	}
	
	/**
	 * 
	 * @param $id
	 * @return unknown_type
	 */
	function getName( $id, $format='bullets' )
	{
		$name = '';
		$cat = HelpDeskHelperCategory::getInstance( $id );
		$pat = '';
		if (intval($cat->parentid) > 0) {
			$pat = HelpDeskHelperCategory::getInstance( $cat->parentid );
		}
		
		switch ($format) 
		{
			case "flat":
				if ($pat) {
					$name .= HelpDeskText::_( $pat->title );
					$name .= " / ";
				}
				$name .= $cat->title ? HelpDeskText::_( $cat->title ) : HelpDeskText::_( 'Uncategorized' );
			  break;
			default:
				if ($pat) {
					$name .= '&bull;&nbsp;&nbsp;';
					$name .= HelpDeskText::_( $pat->title );
					$name .= "<br/>";
				}
				$name .= '&bull;&nbsp;&nbsp;';
				$name .= $cat->title ? HelpDeskText::_( $cat->title ) : HelpDeskText::_( 'Uncategorized' );
			  break;
		}
		
		return $name;
	}
	
	/**
	 * 
	 * @param $userid
	 * @param $catid
	 * @param $returnObject
	 * @return unknown_type
	 */
	function isManager( $catid, $userid, $returnObject='0' ) 
	{
        $success = false;
        $database = HelpDeskConfig::getDBO();
        HelpDeskHelperUtility::import('joomla.utilities.arrayhelper'); //joomla/utilities/arrayhelper.php (line 23)
//        $cats = HelpDeskHelperManager::getCategories( $userid );
//        $catids = HelpDeskArrayHelper::getColumn( $cats, 'id' ); 
        $managers = HelpDeskHelperCategory::getManagers( $catid );
		$managerids = HelpDeskArrayHelper::getColumn( $managers, 'id' );
		
        if (is_array( $managerids ) && in_array( $userid, $managerids )) {
	        $success = true;
            if ($returnObject == '1') {
                $success = HelpDeskHelperCategory::getInstance( $catid );
            }
        }

        return $success;
	}
	
	/**
	 * 
	 * @param $userid
	 * @param $catid
	 * @return unknown_type
	 */
	function addManager( $catid, $userid )
	{
		$success = false;
		$database = HelpDeskConfig::getDBO();
		
	  	$query = "
	  		INSERT INTO 
	  			#__helpdesk_u2c
			SET 
				`userid` = '{$userid}', 
				`categoryid` = '{$catid}' 
		";
		$database->setQuery( $query );
		if ($database->query()) 
		{ 
			$success = true; 
		}
		
		return $success;
	}
	
	/**
	 * 
	 * @param $userid
	 * @param $catid
	 * @return unknown_type
	 */
	function removeManager( $catid, $userid )
	{
		$success = false;
		$database = HelpDeskConfig::getDBO();
		
		$query = "
			DELETE FROM 
				#__helpdesk_u2c
			WHERE 
				`userid` = '{$userid}'
			AND 
				`categoryid` = '{$catid}'
		";
		$database->setQuery( $query );
		if ($database->query()) 
		{ 
			$success = true; 
		}
		
		return $success;		
	}
}